The Utilities component is a collection of miscellaneous utilities which don’t logically belong in the other OPF components. Currently, there is only one utility in the Utilities component: the reference counting utility.
Utilities Component Overview
The Utilities component contains 1 class and 11 methods. You will likely need to know about, and use, the majority of the Utilities component methods.
Directory
FWFoundU
Heritage
FW_TCountedPtr 3
Utilities component classes
There is only one class in the Utilities component, FW_TCountedPtr, which is at the root level of the Utilities component.
Utilities component concepts
The Utilities component provides the reference-counted pointer template class, FW_TCountedPtr, to make it easier to use reference counting. The goal of reference counting is to keep track of how many times an object is referenced so an unreferenced object can be automatically deleted. For more information on reference counting, see “Using FW_TCountedPtr” on page 3.
Additional Utilities component interfaces
There are no additional interfaces.
Component dependencies
Reference-counted pointers are particularly useful when the pointers are value-based, automatic (stack-based) variables. This is true because OPF takes advantage of C++ exception handling. If a reference-counted pointer is a stack-based variable in a given scope, and an exception is thrown out of the scope, then it is important that the destructor of the reference-counted pointer is executed. When OPF is built with compilers that do not yet provide exception handling, OPF uses the OPF Exception Library to provide exception handling emulation. FW_TCountedPtr depends upon exception handling, so if the compiler does not support exception handling, FW_TCountedPtr depends upon the BEL component, FWExcLib. When OPF is built with compilers that support exception handling, FW_TCountedPtr is entirely self-contained and is not dependent on any other OPF components.
Using the Utilities Component
Use the Utilities component to keep track of how many times an object is referenced so an unreferenced object can be automatically deleted.
Subclassing within the Utilities component
Although you can subclass FW_TCountedPtr, that is generally not good C++ style. Instead, you will typically be instantiating FW_TCountedPtr.
Instantiating within the Utilities component
You instantiate the class FW_TCountedPtr.
Extending the Utilities component
It is generally not necessary to extend the Utilities component.
Catching Utilities component exceptions
Methods in the Utilities component do not throw exceptions.
Platform dependencies in the Utilities component
There are no platform-dependent methods in this component.
FW_TCountedPtr Class
Introduction
FW_TCountedPtr provides a mechanism for reference-counted pointers. A reference-counted pointer points to an object of a specific type (tRepresentation) that must contain an internal reference count.
Use FW_TCountedPtr to adjust the reference count inside the representation object. When a reference-counted pointer is:
• copied, the reference count in the representation object is incremented.
• deleted, the reference count in the representation object is decremented.
Disposing of a single reference-counted pointer does not delete the representation object, if it is still being accessed by other reference-counted pointers. When the reference count goes to zero, the representation object is deleted.
Header file
FWCouPtr.h
Heritage
FW_TCountedPtr
Using FW_TCountedPtr
Use FW_TCountedPtr for classes whose instances are often copied through assignment or parameter passing, particularly if the objects are so large or complex that copying is expensive. In addition, use reference-counted pointers when multiple logical copies of an object might exist, though the data itself cannot be copied.
Overview of reference counting
Suppose you are developing a part where you will have many string objects which might contain a small set of string values. Assume you want to create a string class, CString, that can minimize storage requirements by sharing the representation for the string data when two CString objects contain the same string data. The representation is itself an object, managing the shared data and an associated reference count. You will need to design two classes: CString and CStringRep.
In the class CString, implement the assignment operator (among others) such that assigning one string to another string causes sharing of the representation.
class CString
{
public:
operator=(const CString& other);
…
private:
CStringRep *fRep; // pointer to CStringRep
};
Since the object is shared, a reference count field in the class CStringRep is needed to be sure that the CStringRep object is only deleted when there are no more CString objects using it.
class CStringRep
{
public:
long Length();
…
private:
char *fRep; // pointer to a string
int fCount; // reference count field
};
Figure 1-1 on page 5 illustrates the state of two string objects a and b after the assignment b = a. While a and b name separate CString objects, both objects point to the same CStringRep object.
Figure 11 How to handle strings with reference counting
Adding reference-counted pointers
FW_TCountedPtr makes it relatively easy to add reference counting to a design. You can modify the above design to use FW_TCountedPtr very easily, by doing the following two things:
1) Implement the methods IncrementReferenceCount and DecrementReferenceCount in the class CStringRep. This is the interface FW_TCountedPtr uses to adjust the reference count inside the representation object.
2) Use the template class FW_TCountedPtr<CStringRep> in place of the class CString. This might be done using a typedef:
typedef CString FW_TCountedPtr<CStringRep>;
Objects of FW_TCountedPtr<T> behave very much like pointers to T.
In general, if you want to add reference counting to your own data structures, you will need to design a representation class CYourClassRep and then instantiate FW_TCountedPtr<CYour–ClassRep> for your class. Whenever a reference-counted pointer class is used, there must be a corresponding representation class. This representation class is generally an implementation detail. FW_TCountedPtr makes no effort to hide these implementation details.
Idioms for using reference-counted pointers
It is much more convenient to type and read the name CString than it is to type and read the name FW_TCountedPtr<CString–Rep>. For these reasons, it is generally preferable to encapsulate the reference-counted pointer within another class. You can subclass FW_TCountedPtr, but that is generally not good C++ style. Instead, create a new class that contains a FW_TCountedPtr<T> field. For example, you can modify CString as follows:
class CString
{
public:
long Length() {fRep->Length();}
…
private:
FW_TCountedPtr<CStringRep> fRep;
};
With this idiom, you need only look at the CString class, which explicitly reimplements all the functions of CStringRep with inline functions.
Dereferencing
Overloading the dereferencing operator->() is primarily useful for creating smart pointers, that is, objects that act like pointers, and in addition, perform some action whenever another object is accessed through them. The difference between a smart pointer and an ordinary pointer is that a smart pointer is used on an object of a class and is not a pointer to an object. For example, if X is a class with an operator->() method, and Y() is a method of some other class, then
X xobj;
xobj->Y();
is evaluated as
(xobj.operator->())->Y();
This means that operator->() must return an object of a class. This class must contain a definition for operator->(). The operator->() is then called again for the new object and this process is repeated recursively until the result is a pointer to a class object containing the Y() method.
FW_TCountedPtr<T> implements operator->(), but a client of FW_TCountedPtr<T> must look at the interface of T to know what fields are available (and accessible). For example, you must look at the interface of CStringRep (below) to know that the public method, Length(), is accessible to FW_TCounted–Ptr<CStringRep>.
class CStringRep
{
public:
long Length();
…
private:
char *fRep; // pointer to a string
int fCount; // reference count field
};
FW_TCountedPtr subclasses
There are no subclasses of this class.
Related classes
OPF uses reference counting in the Files, Graphics, and Resources components.
Subclassing FW_TCountedPtr
You might subclass FW_TCountedPtr<CYourClassRep> and name the resulting class CYourClass. This would allow you to add extra constructors and provide a more convenient class name. However, you should be sure to read the section “Idioms for using reference-counted pointers” on page 6, since it is generally preferable to not subclass this class.
FW_TCountedPtr Methods
FW_TCountedPtr();
Default constructor. Creates a NULL pointer (a pointer whose value is 0). Such an instance does not point to any representation object.
FW_TCountedPtr(tRepresentation* rep);
Creates a new reference-counted pointer that points to the representation object passed in as a parameter, and increments the reference count by one.
Copy constructor. Creates a new reference-counted pointer that points to the same representation object as the other reference-counted pointer points to, and increments the reference count by one.
~FW_TCountedPtr();
Destroys the reference-counted pointer. Decrements the reference count in the representation object and deletes the representation object if the reference count is zero.
int operator!=(const FW_TCountedPtr<tRepresentation>& other) const;
Returns TRUE if the reference-counted pointer points to a different representation object and FALSE if it does not.
tRepresentation& operator*() const;
Provides access to the representation object. This operator should be used only if operator->() is not sufficient.
tRepresentation* operator->() const;
Provides access to fields of the representation object. For more information on smart pointers, see “Dereferencing” on page 6.
Assignment operator. Point this reference-counted pointer to the same representation object as the other reference-counted pointer points to, and increment the reference count by one.
Assignment operator. Point this reference-counted pointer to the representation object passed in as a parameter, and increment the reference count by one.
int operator==(const FW_TCountedPtr<tRepresentation>& other) const;
Returns TRUE if the reference-counted pointer points to the same representation object and FALSE if it does not.
operator const void*() const;
Use to test if the reference-counted pointer is a NULL pointer.